<?php
namespace App\Services;

use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\DB;
use App\Models\Goods;
use App\Models\User;
use App\Models\IntegralRule;
use App\Models\CouponsConfig;
class GoodsSeckillService{

    /**
     * 秒杀逻辑处理
     * @param User $user 参与秒杀的人
     * @param int $goods_id 参与秒杀的产品id
     * @throws \Throwable
     */
        public function goodsSeckill(User $user,int $goods_id){
            //redis中产品库存减一
            Redis::decr('seckill_sku_'.$goods_id);
            //事务开始
            Db::transaction(function () use ($user,$goods_id){
                //查找卡券的过期天数
                $pass_day = IntegralRule::getPassDay();
                //查找数据库中该产品的信息
                $goods = Goods::where("id",$goods_id)
                            ->where("on_sale",true)
                            ->where("is_seckill",true)
                            ->first();
                //判断产品是否处于在售且秒杀期间
                //未处于秒杀期间，redis库存加一，返回错误
                if (!$goods){
                    //商品错误
                    Redis::incr('seckill_sku_'.$goods_id);
//                    abort(501,"商品信息错误");
                    abort(412,"商品信息错误");
                }
                if ($goods->is_before_start) {
                        //秒杀未开始
                    Redis::incr('seckill_sku_'.$goods_id);
                    abort(412,"秒杀尚未开始");
                }
                if ($goods->is_after_end) {
                        //秒杀已结束
                    Redis::incr('seckill_sku_'.$goods_id);
                    abort(412,"秒杀已结束");
                }

                //判断用户所拥有的积分是否足以购买该产品
                    //不能购买redis库存加一，返回错误
                if ($user->userIntegral->integral<$goods->integral){
                    Redis::incr('seckill_sku_'.$goods_id);
                    abort(412,"积分不足");
                }

                //判断用户在产品秒杀期间是否参与过该产品的秒杀
                // 参与过的话限购 不能买 redis库存加一，返回错误
                $count = $user->coupons()->where("goods_id",$goods_id)
                                ->whereBetween("created_at",[$goods->flash_sale_start_time,$goods->flash_sale_end_time])
                                ->count();
                if ($count>0){
                    Redis::incr('seckill_sku_'.$goods_id);
                    abort(412,"单次活动产品限购一件");
//                    throw new InternalErrorException("单次活动产品限购一件");
                }

                //****************************涉及到数据变动的部分*************************//
                //用户积分使用记录新增一 （在积分使用记录的监听器里边处理了用户积分的变动）
                $user->userIntegralLogs()->create([
                   "integral"=>-$goods->integral,
                    "des"    =>"参与".$goods->short_name."的秒杀活动",
                    "is_checked"=>true,
                ]);
                $flash_sale_price = $goods->flash_sale_price?$goods->flash_sale_price:0;
                //新增用户卡券 、卡券发放完毕 秒杀结束 (卡券发放通知在模型事件的监听器里边)
                $user->coupons()->create([
                    "end_date"=>now()->addDays($pass_day)->toDateString(),
                    "title"   =>$goods->short_name."券",
                    "descript"=>$goods->coupon_des?$goods->coupon_des:"持此券到店可享".$flash_sale_price."元秒杀价购买".$goods->short_name."一件",
                    "goods_id"=>$goods->id,
                    "type"=>CouponsConfig::COUPONS_TYPE_SECKILL
                ]);
                //商品的秒杀库存减一
                $goods->decrement("flash_sale_number");

            });

            //事务结束



        }
}
